home *** CD-ROM | disk | FTP | other *** search
- DATA SEGMENT PUBLIC 'DATA'
- TITLE__ DB 'TITLE: DAY OF WEEK FOR MS FORTRAN'
- COPY_R DB ' (C) John R. Petrocelli'
- DB ' Schenectady,NY '
- DB ' 01/16/86 '
-
- INITIAL_YEAR EQU 1901 ; 1901 INITIAL YEAR
- INITIAL_DAY EQU 3-1 ; TUESDAY 01/01/1901 CORRECTED
- ; (-1) FOR COMPUTATION SINCE WE
- ; MUST START WITH 0
- MAX_YEAR EQU 2099 ; HIGHEST YEAR WE CAN CALCULATE
- ; FOR THIS ROUTINE
-
- ; *** NOTE ***
- ; A CENTURY IS ONLY A LEAP YEAR
- ; IF IT IS EVENLY DIVISIBLE BY
- ; 400. THEREFORE THE YEAR 2000
- ; IS A LEAP YEAR.
-
- LEAP_YEAR_OFF EQU 0
- LEAP_YEAR_ON EQU 1
- CR EQU 0DH ; CARRAGE RETURN
- LF EQU 0AH ; LINE FEED
- EOM EQU '$' ; END OF MESSAGE INDICATOR
-
- ERR_MSG_HDR DB CR,LF,'WEEKDY SUBROUTINE PARAMETER ERROR',EOM
- ERR_MSG_YR DB CR,LF,'YEAR MUST BE > 1901 AND < 2099',CR,LF,EOM
- ERR_MSG_MO DB CR,LF,'MONTH LESS THAN 1 OR GREATER THAN 12',CR,LF,EOM
- ERR_MSG_DY DB CR,LF,'DAY LESS THAN 1 OR GREATER '
- DB CR,LF,'THAN # OF DAYS IN SPECIFIED MONTH',CR,LF,EOM
-
- LEAP_YR DW 0
- YEAR DW 0
- MONTH DW 0
- DAY DW 0
- WEEK_DY DW 0
- XLAT_MONTH DB 31,28,31 ;JAN,FEB,MAR
- DB 30,31,30 ;APR,MAY,JUN
- DB 31,31,30 ;JUL,AUG,SEP
- DB 31,30,31 ;OCT,NOV,DEC
- DB 29 ;FEB IN LEAP YEAR
-
- DATA ENDS
- DGROUP GROUP DATA
- CODE SEGMENT 'CODE'
- ASSUME CS:CODE,DS:DGROUP,SS:DGROUP
- PUBLIC WEEKDY
- WEEKDY PROC FAR
- PUSH BP ; SAVE FRAME POINTER
- PUSH AX ; SAVE REGISTERS
- PUSH BX
- PUSH DX
- MOV BP,SP ; FRAME POINTER POINTS TO STACK PTR
-
- MOV WEEK_DY,INITIAL_DAY ; SETUP INITIAL VALUES
- MOV LEAP_YR,LEAP_YEAR_OFF
-
- LES BX,DWORD PTR[BP+24] ; ES:BX POINTS TO MONTH
- MOV AX,[BX] ; GET MONTH INTO AX
- MOV MONTH,AX ; STORE MONTH
-
- LES BX,DWORD PTR[BP+20] ; ES:BX POINTS TO DAY
- MOV AX,[BX] ; GET DAY IN AX
- MOV DAY,AX ; STORE DAY
-
- LES BX,DWORD PTR[BP+16] ; ES:BX POINTS TO YEAR
- MOV AX,[BX] ; GET YEAR INTO AX
- MOV YEAR,AX ; STORE YEAR
-
- CMP AX,INITIAL_YEAR ; COMPARE YEAR WITH THE LOWEST WE
- ; CAN PROCESS
- JAE GOOD_LOW ; JUMP IF GOOD YEAR
- JMP ERROR_YR ; JUMP TO ERROR IF TOO LOW A YEAR
- GOOD_LOW:
- CMP AX,MAX_YEAR ; COMPARE YEAR WITH THE HIGHEST WE
- ; CAN PROCESS
- JBE GOOD_YEAR ; JUMP IF YEAR IN OUR RANGE OF CALC
- JMP ERROR_YR ; JUMP TO ERROR IF TOO HIGH A YEAR
- GOOD_YEAR:
- MOV BX,4 ; LEAP YEAR DIVISOR
- MOV DX,0
- DIV BX ; DIVIDE YEAR BY 4
- CMP DX,0 ; IS REMAINDER 0 ?
- JNE NOT_LEAP_REQ ; JUMP IF NOT LEAP YEAR
- MOV LEAP_YR,LEAP_YEAR_ON ; SET LEAP YEAR FLAG SINCE REQUEST
- ; IS LEAP YEAR
-
- ; -------------------------------------------------------------------
- ; PROCESS YEAR
- ; -------------------------------------------------------------------
- NOT_LEAP_REQ:
-
- MOV AX,INITIAL_YEAR ; PUT START YEAR IN AX
- CHK_YR:
- CMP AX,YEAR ; IS AX EQUAL TO REQUESTED YEAR
- JE CHK_MONTH ; IF YES CHECK DAY COUNT
- PUSH AX ; SAVE THE WORKING YEAR
- MOV BX,4 ; LEAP YEAR DIVISOR
- MOV DX,0
- DIV BX ; DIVIDE YEAR BY 4
- MOV AX,365 ; 365 DAYS/YR IN AX
- CMP DX,0 ; IS REMAINDER 0 ?
- JNE NOT_LEAP_YR ; JUMP IF NOT LEAP YEAR
- INC AX ; INCREMENT AX IF LEAP YEAR-366 DY
-
- NOT_LEAP_YR:
- MOV BX,7 ; DAY OF WEEK DIVISOR
- MOV DX,0
- DIV BX ; DIVIDE TO GET WEEKDAY OFFSET
- ; IN DX
- ADD DX,WEEK_DY ; ADD CURRENT DAY OF WEEK TO
- ; WEEKDAY OFFSET
- CMP DX,8 ; IS IT GREATER THAN 7 ?
- JL OK_DAY1 ; NO THEN OK
- SUB DX,7 ; YES THEN SUBTRACT 7
- OK_DAY1:
- MOV WEEK_DY,DX ; SAVE RESULTING DAY OF WEEK
-
- POP AX ; GET BACK VALUE OF AX
- INC AX ; ADD 1 TO AX FOR NEXT YEAR
- JMP CHK_YR ; DO AGAIN
-
- ; -------------------------------------------------------------------
- ; PROCESS MONTH
- ; -------------------------------------------------------------------
- CHK_MONTH:
- MOV AX,1 ; PUT START MONTH IN AX
- CMP MONTH,AX ; CHECK IF MONTH < 0
- JAE CHK_MO ; JUMP IF OK
- JMP ERROR_MO ; JUMP IF ERROR
- CHK_MO:
- CMP AX,MONTH ; IS AX EQUAL TO REQUESTED YEAR
- JE CHK_DAY ; IF YES CHECK DAY COUNT
- PUSH AX ; SAVE THE WORKING YEAR
- CMP AX,2 ; ARE WE COMPUTING FEBRUARY DAYS ?
- JNE NO_FEBRUARY ; NO - JUMP OVER
- CMP LEAP_YR,0 ; YES - IS LEAP YEAR FLAG SET ?
- JZ NO_FEBRUARY ; NO - JUMP OVER
- ADD AX,11 ; ADD AX WITH OFFSET FOR TRANSLATE
- NO_FEBRUARY:
- LEA BX,XLAT_MONTH ; BX POINTS TO TRANSLATE TABLE
- DEC AX ; CORRECT AX FOR TABLE START
- XLAT XLAT_MONTH ; TRANSLATE - AX HAS DAYS IN MONTH
-
- MOV BX,7 ; DAY OF WEEK DIVISOR
- MOV DX,0
- DIV BX ; DIVIDE TO GET WEEKDAY OFFSET
- ; IN DX
- ADD DX,WEEK_DY ; ADD CURRENT DAY OF WEEK TO
- ; WEEKDAY OFFSET
- CMP DX,8 ; IS IT GREATER THAN 7 ?
- JL OK_DAY2 ; NO THEN OK
- SUB DX,7 ; YES THEN SUBTRACT 7
- OK_DAY2:
- MOV WEEK_DY,DX ; SAVE RESULTING DAY OF WEEK
-
- POP AX ; GET BACK VALUE OF AX
- INC AX ; ADD 1 TO AX FOR NEXT MONTH
- JMP CHK_MO ; DO AGAIN
-
-
- ; -------------------------------------------------------------------
- ; PROCESS DAY
- ; -------------------------------------------------------------------
- CHK_DAY:
- CMP AX,2 ; ARE WE ASKING FOR FEBRUARY DAYS ?
- JNE NOT_IN_FEB ; NO - JUMP OVER
- CMP LEAP_YR,0 ; YES - IS LEAP YEAR FLAG SET ?
- JZ NOT_IN_FEB ; NO - JUMP OVER
- ADD AX,11 ; ADD AX WITH OFFSET FOR TRANSLATE
- NOT_IN_FEB:
- LEA BX,XLAT_MONTH ; BX POINTS TO TRANSLATE TABLE
- DEC AX ; CORRECT AX FOR TABLE START
- XLAT XLAT_MONTH ; TRANSLATE - AX HAS DAYS IN MONTH
- CMP DAY,AX ; BE SURE DAY NOT > DAYS IN MONTH
- JA ERROR_DY ; JUMP IF ERROR
- MOV AX,DAY ; PUT REQUESTED DAY IN AX
-
- MOV BX,7 ; DAY OF WEEK DIVISOR
- MOV DX,0
- DIV BX ; DIVIDE TO GET WEEKDAY OFFSET
- ; IN DX
- ADD DX,WEEK_DY ; ADD CURRENT DAY OF WEEK TO
- ; WEEKDAY OFFSET
- CMP DX,8 ; IS IT GREATER THAN 7 ?
- JL OK_DAY3 ; NO THEN OK
- SUB DX,7 ; YES THEN SUBTRACT 7
- OK_DAY3:
- MOV WEEK_DY,DX ; SAVE RESULTING DAY OF WEEK
-
-
- ; -------------------------------------------------------------------
- ; WE NOW KNOW WHAT DAY OF THE WEEK IT IS
- ; -------------------------------------------------------------------
- LES BX,DWORD PTR[BP+12] ; ES:BX POINTS TO RETURN VALUE
- ; FOR DAY OF WEEK
- MOV AX,WEEK_DY ; GET DAY OF WEEK INTO AX
- MOV [BX],AX ; STOW IT FOR RETURN
- JMP BYE ; JUMP OVER ERROR REPORTS
- ERROR_YR:
- LEA DX,ERR_MSG_YR ; BAD YEAR ERROR MESSAGE
- JMP MESSAGE
- ERROR_MO:
- LEA DX,ERR_MSG_MO ; BAD MONTH ERROR MESSAGE
- JMP MESSAGE
- ERROR_DY:
- LEA DX,ERR_MSG_DY ; BAD DAY ERROR MESSAGE
- MESSAGE:
- PUSH DX ; SAVE ERROR MSG ADDRESS
- LEA DX,ERR_MSG_HDR ; DX POINTS TO ERROR MSG HEADER
- MOV AX,0900H ; LOAD AX WITH PRINT FUNCTION
- INT 21H ; PRINT MESSAGE
- POP DX ; RESTORE ERROR MSG ADDRESS
- MOV AX,0900H ; LOAD AX WITH PRINT FUNCTION
- INT 21H ; PRINT MESSAGE
-
- BYE:
- POP DX ; RESTORE REGISTERS
- POP BX
- POP AX
- POP BP ; RESTORE FRAME POINTER
- RET 16 ; RETURN AND POP 16 BYTES OFF
- ; STACK
- WEEKDY ENDP
-
- CODE ENDS
- END